package cn.ljy.authority.config.sms;

import cn.ljy.common.exception.model.SmsException;
import com.aliyun.auth.credentials.Credential;
import com.aliyun.auth.credentials.provider.StaticCredentialProvider;
import com.aliyun.sdk.service.dysmsapi20170525.AsyncClient;
import com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsResponse;
import darabonba.core.client.ClientOverrideConfiguration;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

/**
 * 阿里云短信服务（Spring管理，自动初始化/销毁连接）
 */
@Slf4j
@Service // 注入Spring容器
//@RequiredArgsConstructor // 构造器注入SmsProperties（避免手写@Autowired）
public class SmsService {

    @Autowired
    private SmsProperties smsProperties;
    private AsyncClient asyncClient; // 短信客户端（全局单例）

    /**
     * Spring启动时初始化短信客户端（PostConstruct：构造器执行后调用）
     */
    @PostConstruct
    public void initClient() {
        try {
            // 1. 构建凭证提供者
            StaticCredentialProvider credentialProvider = StaticCredentialProvider.create(
                    Credential.builder()
                            .accessKeyId(smsProperties.getAccessKeyId())
                            .accessKeySecret(smsProperties.getAccessKeySecret())
                            .build()
            );

            // 2. 构建异步客户端
            this.asyncClient = AsyncClient.builder()
                    .credentialsProvider(credentialProvider)
                    .overrideConfiguration(
                            ClientOverrideConfiguration.create()
                                    .setEndpointOverride(smsProperties.getEndpoint())
                    )
                    .build();

            log.info("阿里云短信客户端初始化成功");
        } catch (Exception e) {
            log.error("阿里云短信客户端初始化失败", e);
            throw new SmsException("短信客户端初始化异常", e);
        }
    }

    /**
     * 发送手机验证码
     *
     * @param phoneNumbers 手机号（单个，批量请业务层循环调用）
     * @param code         验证码（4-6位数字）
     * @return 发送响应
     * @throws SmsException 发送异常（含错误信息和requestId）
     */
    public SendSmsResponse sendCode(String phoneNumbers, String code) throws SmsException {
        // 1. 参数校验
        validateParams(phoneNumbers, code);

        // 2. 构造请求
        SendSmsRequest request = SendSmsRequest.builder()
                .phoneNumbers(phoneNumbers.trim())
                .signName(smsProperties.getSignName())
                .templateCode(smsProperties.getTemplateCode())
                .templateParam("{\"code\":\"" + code + "\"}") // 模板参数（JSON格式）
                .build();

        // 3. 发送请求（同步等待结果，带超时）
        try {
            CompletableFuture<SendSmsResponse> future = asyncClient.sendSms(request);
            SendSmsResponse response = future.get(
                    smsProperties.getRequestTimeout().toMillis(),
                    TimeUnit.MILLISECONDS
            );

            // 4. 校验响应结果
            if (!"OK".equalsIgnoreCase(response.getBody().getCode())) {
                String errorMsg = String.format(
                        "短信发送失败：Code=%s, Message=%s, RequestId=%s",
                        response.getBody().getCode(),
                        response.getBody().getMessage(),
                        response.getBody().getRequestId()
                );
                log.error(errorMsg);
                throw new SmsException(errorMsg);
            }

            log.info("短信发送成功：手机号={}, BizId={}, RequestId={}",
                    phoneNumbers, response.getBody().getBizId(), response.getBody().getRequestId());
            return response;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("短信发送被中断：手机号={}", phoneNumbers, e);
            throw new SmsException("短信发送中断，手机号=" + phoneNumbers, e);
        } catch (java.util.concurrent.TimeoutException e) {
            log.error("短信发送超时：手机号={}", phoneNumbers, e);
            throw new SmsException("短信发送超时，手机号=" + phoneNumbers, e);
        } catch (SmsException e) {
            throw e; // 直接抛出自定义异常
        } catch (Exception e) {
            log.error("短信发送异常：手机号={}", phoneNumbers, e);
            throw new SmsException("短信发送失败，手机号=" + phoneNumbers, e);
        }
    }

    /**
     * 参数校验（手机号+验证码）
     */
    private void validateParams(String phoneNumbers, String code) throws SmsException {
        // 手机号非空校验
        if (phoneNumbers == null || phoneNumbers.trim().isEmpty()) {
            throw new SmsException("手机号不能为空");
        }
        // 手机号格式校验（大陆手机号）
        String phoneRegex = "^1[3-9]\\d{9}$";
        if (!Pattern.matches(phoneRegex, phoneNumbers.trim())) {
            throw new SmsException("手机号格式不合法：" + phoneNumbers);
        }
        // 验证码校验（4-6位数字）
        if (code == null || !Pattern.matches("\\d{4,6}", code)) {
            throw new SmsException("验证码必须为4-6位数字：" + code);
        }
    }

    /**
     * Spring关闭时销毁客户端（PreDestroy：容器销毁前调用）
     */
    @PreDestroy
    public void closeClient() {
        if (asyncClient != null) {
            try {
                asyncClient.close();
                log.info("阿里云短信客户端已销毁");
            } catch (Exception e) {
                log.error("阿里云短信客户端销毁失败", e);
            }
        }
    }
}